﻿using System;
using System.Linq;
using System.Collections.Generic;
using System.Text;
using Silvermoon.Shapes;
using Silvermoon.OpenGL;
using System.Drawing;
using Silvermoon.Utils;
using Silvermoon.Animations;
using Silvermoon.Images;
using Silvermoon.Windows;

namespace Silvermoon.Controls
{
    /// <summary>
    /// Control which renders 4 dots decelerating from left edge then accelerating to right edge.
    /// This control is used when the application is currently busy getting some data.
    /// </summary>
    public class ProgressingControl : ChromeControl
    {
        const int numDots = 4;
        const int sz = 8;
        private Shape[] dots = new Shape[numDots];
        private static readonly Margin margin = new Margin(0, null, 0, null);
        private static readonly EasingFunctionBase easeOut = new ExponentialEase { Mode = EasingMode.EaseOut, Exponent = 10d };
        private static readonly EasingFunctionBase easeIn = new ExponentialEase { Mode = EasingMode.EaseIn, Exponent = 10d };
        private float progress = -1;

        public ProgressingControl()
            : base()
        {
            Margin = margin;
            Height = 16;
            Visible = false;

            for (int i = 0; i < numDots; i++)
            {
                Shape s = dots[i] = new ImageShape { Image = SysImages.Dot, Size = new Size(8, 8), UseTextColor = true };
                //Shape s = dots[i] = new RectangleShape { Size = new Size(8, 8), Color = PhoneColors.Dark };
                Shapes.AddLast(s);
            }
        }

        protected override void Dispose(bool dispose)
        {
            Visible = false;
            base.Dispose(dispose);
        }

        protected override void OnTextColorChanged()
        {
            foreach (Shape s in dots) s.Color = TextColor;
            base.OnTextColorChanged();
        }

        protected override void OnVisibleChanged()
        {
            base.OnVisibleChanged();
            if (Screen != null)
            {
                if (Visible)
                {
                    Screen.Tick += new EventHandler<Silvermoon.Core.TimeEventArgs>(OnTick);
                }
                else
                {
                    Screen.Tick -= OnTick;
                }
            }
        }


        void OnTick(object sender, Silvermoon.Core.TimeEventArgs e)
        {
            float progress = this.progress; // e.Tick / 1000f;
            int w2 = Width / 2;
            int h0 = Height;
            int dx = -10 * numDots / 2;
            for (int i = 0; i < numDots; i++)
            {
                Shape s = dots[i];
                int x = GetX(progress) + w2 + dx;
                int h = s.Height;
                s.Location = new Point(x, (h0 - h) / 2);
                progress += 0.1f;
                dx += 10;
            }
            this.progress += 0.05f;
            if (this.progress == 2f) this.progress = 0f;

            Invalidate(InvalidationFlag.Appearance);
        }

        private int GetX(float progress)
        {
            progress = (float)Math.IEEERemainder(progress, 2d);

            float w = Width * 6;
            if (progress < 0)
            {
                float p2 = 1 + progress;
                float e = easeOut.Ease(p2) * w;
                return (int)(-w + e + 25f * progress - 0f);
            }
            else
            {
                var e = easeIn.Ease(progress) * w;
                return (int)(e + 25f * progress - 0f);
            }
        }

    }

}
